//------------------------------------------------------------
//  Filename: camera_dc.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2019-07-02 21:03
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module CAMERA_DC ( 
    input  wire        clk_100mhz,
    input  wire        resetn    ,
    //camera input
    input  wire        camera_video_en,  
    input  wire        camera_pclk,
    input  wire        camera_resetn,
    input  wire [7:0]  camera_yuv422, 
    input  wire        camera_h_sync,  // HREF --- function as data_valid 
    input  wire        camera_v_sync,  // VSYN --- fram sync ,plority high
    output reg  [31:0] camera_param,
    output reg  [31:0] camera_error,
    output reg  [7:0]  camera_bright,
    input  wire [15:0] camera_x_scaler,
    input  wire [15:0] camera_y_scaler,

    input  wire [15:0] x_org_cnt,
    input  wire [15:0] y_org_cnt,

    output reg [32:0]  vdma_din,
    output reg         vdma_v,

    output reg [8:0]   coproc_din,
    output reg         coproc_v
);   
//--------------------------------------------------------
wire     clk = clk_100mhz;
wire     rst = ~(resetn&camera_resetn);
//--------------------------------------------------------
reg[2:0]  h_sync;
reg[2:0]  v_sync;
reg[23:0] p_data;
reg       d_last;
//--------------------------------------------------------
wire [7:0]  camera_start_x = camera_x_scaler[7:0];
wire [7:0]  camera_start_y = camera_y_scaler[7:0];
wire [15:0] camera_end_x   = camera_start_x + {camera_x_scaler[15:8],4'b0}; // 16 x set value
wire [15:0] camera_end_y   = camera_start_y + {camera_y_scaler[15:8],4'b0};  
//--------------------------------------------------------
always@(posedge camera_pclk ) h_sync <= {h_sync[1:0],camera_h_sync};
always@(posedge camera_pclk ) v_sync <= {v_sync[1:0],camera_v_sync};
always@(posedge camera_pclk ) p_data <= {p_data[15:0],camera_yuv422};
always@(posedge camera_pclk ) d_last <= (v_sync[2:1] == 2'b01)?1'b1:1'b0; 
//-------------------------------------------------------- 
reg[8:0]  s0_axis_tdata   ;
reg       s0_axis_tvalid  ;
wire[8:0] m0_axis_tdata   ;
wire      m0_axis_tvalid  ;
wire      m0_empty        ;
//-------------------------------------------------------- 
always @(posedge camera_pclk,posedge rst) begin
    if(rst)begin 
        s0_axis_tdata  <= 8'b0;    
        s0_axis_tvalid <= 1'b0;    
    end 
    else begin 
        s0_axis_tdata  <= {d_last,p_data[15:8]};    
        s0_axis_tvalid <= (h_sync[1]|d_last);    
    end 
end 
//-------------------------------------------------------- 
CAMERA_SYNC sync_i0 (
    .rst_n   ( ~rst             ) ,

    .wr_clk  ( camera_pclk      ) ,
    .wr_din  ( s0_axis_tdata    ) ,
    .wr_en   ( s0_axis_tvalid   ) ,

    .rd_clk  ( clk              ) ,
    .rd_en   ( m0_axis_tvalid   ) ,
    .rd_dout ( m0_axis_tdata    ) ,
    .empty   ( m0_empty         ) 
);
//-------------------------------------------------------- 
assign   m0_axis_tvalid = ~m0_empty;
//********************************************************
//--
//--  CLK 100M domain
//--
//********************************************************
reg[7:0] sync_tdata  ;
reg      sync_last   ;
reg      sync_data_v ;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        sync_tdata  <= 'b0;
        sync_last   <= 'b0;
        sync_data_v <= 'b0;
    end 
    else begin
        sync_tdata  <= m0_axis_tdata[7:0] ;
        sync_last   <= m0_axis_tdata[8]&m0_axis_tvalid;
        sync_data_v <= m0_axis_tvalid ;
    end
end
//-------------------------------------------------------- 
reg [31:0] d_counter;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        d_counter <= 0;
    end 
    else if(sync_data_v)begin
        d_counter <= (sync_last)?0:(d_counter + 1);
    end
end
//--------------------------------------------------------
reg [7:0] f_counter;
reg[31:0] second_cntr;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        second_cntr <= 32'b0;  
        f_counter   <= 8'b0;  
    end 
    else begin 
        second_cntr <= (second_cntr < (1000_000_00 -1))?(second_cntr + 1):0;
        if(second_cntr == (1000_000_00 -1)) begin
            f_counter   <= 8'b0;  
        end
        else if(sync_last)begin
            f_counter   <= f_counter + 1;  
        end
    end 
end 
//--------------------------------------------------------
reg[7:0]  raw_rate;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        raw_rate <= 8'b0;    
    end 
    else if(second_cntr == (1000_000_00 -1)) begin 
        raw_rate <= f_counter;    
    end 
end 
//--------------------------------------------------------
reg[7:0]  rgb_raw_data;
reg       rgb_raw_v;
reg       rgb_raw_last;
//--------------------------------------------------------
wire  gray_data = (d_counter[0] == 1'b0)?1'b1:1'b0;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin
        rgb_raw_data <= 8'b0;
        rgb_raw_v    <= 1'b0;
	    rgb_raw_last <= 1'b0;
    end
    else begin
        rgb_raw_data <= (sync_data_v&gray_data) ? sync_tdata : rgb_raw_data; // fixed data ,Y to GRAY only,or color convert function
        rgb_raw_v    <= (sync_data_v&gray_data)|sync_last;
	    rgb_raw_last <= sync_last;
    end 
end
//--------------------------------------------------------
reg[31:0]   raw_bright_sum ;
reg[31:0]   raw_data_cntr  ;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        raw_bright_sum <= 32'b0;        
        raw_data_cntr  <= 32'b0;        
    end 
    else if(rgb_raw_v&rgb_raw_last)begin 
        raw_bright_sum <= 32'b0;        
        raw_data_cntr  <= 32'b0;        
    end    
    else if(rgb_raw_v&&(raw_data_cntr < 1024))begin  
        raw_bright_sum <= raw_bright_sum + rgb_raw_data;        
        raw_data_cntr  <= raw_data_cntr + 32'b1;        
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        camera_bright <= 8'b0;
    end 
    else if(rgb_raw_v&rgb_raw_last)begin 
        camera_bright <= raw_bright_sum[17:10];
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        camera_param <= 0;
    end 
    else if(sync_last) begin
        camera_param <= {raw_rate,d_counter[24:1]};
    end
end
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        camera_error[15:0] <= 0;
    end 
    else if(sync_last&&(d_counter[24:1] != 307200)) begin
        camera_error[15:0] <= camera_error[15:0] + 16'h1;
    end
end
//--------------------------------------------------------
reg[15:0] x_cntr;
reg[1:0]  x_scnt;
reg[15:0] y_cntr;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        x_cntr    <= 16'h0;  
        x_scnt    <= 2'b0;  
    end 
    else if(rgb_raw_v) begin
        if(rgb_raw_last)begin 
            x_cntr <= 16'h1;    
        end 
        else begin
            x_cntr <= (x_cntr < x_org_cnt)? (x_cntr + 16'h1):16'h1; 
        end   

		  if((x_cntr > camera_start_x)&&(y_cntr > camera_start_y)&&(x_cntr <= camera_end_x)&&(y_cntr <= camera_end_y)) begin
            x_scnt <= x_scnt + 1'b1;
        end
        else begin
            x_scnt <= 2'b0;  
        end
	 end 
end 
//--------------------------------------------------------
reg[31:0] gth_data;
reg       gth_last;
reg       gth_v;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gth_data  <= 32'b0;
        gth_last  <= 1'b0;
	    gth_v     <= 1'b0;
    end 
    else if(rgb_raw_v) begin
        gth_data <= {gth_data[23:0],rgb_raw_data[7:0]};
        gth_last <= ((x_cntr == camera_end_x)&&(y_cntr == camera_end_y))?1'b1:1'b0;      		  
        gth_v    <= ((x_cntr == camera_end_x)&&(y_cntr == camera_end_y)||(x_scnt == 2'b11)) ? 1'b1:1'b0;   
	 end 
    else begin
        gth_last <= 1'b0;
        gth_v    <= 1'b0;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        vdma_din  <= 33'b0;
        vdma_v    <= 1'b0;
    end
    else begin
        vdma_din  <= {gth_last,gth_data};
        vdma_v    <= gth_v;	 
	end
end
//--------------------------------------------------------
wire new_line = (x_cntr == 1)?1'b1:1'b0;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        y_cntr <= 16'h0;    
    end 
    else if(rgb_raw_last)begin 
        y_cntr <= 16'h0;    
    end 
    else if(new_line&coproc_v) begin
        y_cntr <= y_cntr + 16'h1;    
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        coproc_din   <= 9'b0; 
        coproc_v     <= 1'b0;   
    end 
    else begin
        coproc_din   <= {rgb_raw_last,rgb_raw_data}; 
        coproc_v     <= rgb_raw_v;   
    end
end 

endmodule
